// 将 AST 转换成可执行代码
export function evaluate (root) {

  const NumbericLiteral = ({value}) => {
    return value;
  };

  const BinaryExpression = ({left, operatorToken: op, right}) => {
    const leftValue = visit(left);
    const rightValue = visit(right);
    
    switch(op.type) {
      case "MulToken": 
        return leftValue * rightValue;
      case "PlusToken":
        return leftValue + rightValue;
      case "DivToken":
        return  leftValue / rightValue;
      default:
        throw new Error(`unknow operator "${op.type}" at 
        ${op.loc.file}:${op.loc.start.line}:${op.loc.start.column}`);
    }
  };

  const visit = (node) => {
    if (node == null) throw "something";
    switch (node.type) {
      case "BinaryExpression": 
        return BinaryExpression(node);
      case "NumbericLiteral":
        return NumbericLiteral(node);
      default:
        throw new Error(`unknow node type "${node.type}" at 
        ${node.loc.file}:${node.loc.start.line}:${node.loc.start.column}`);
    }
  }

  return visit(root);
}